#include <dspSimulator/instruction/birp.h>


bool BIRP::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return checkStandardCondition(dspMachine);
}

void BIRP::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                             std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> BIRP::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<BIRP> birp;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<10>(data, 13, 0b0011000000) && checkBits<10>(data, 2, 0b0000111000)) {
            birp = std::make_shared<BIRP>(dspInstInfo->getAddress(), baseCycle);
            birp->creg_z = extractBits<4>(data, 28);
            birp->dst = extractBits<5>(data, 23).to_ulong();
            birp->x = data[12];
            birp->s = data[1];
            birp->p = data[0];
            birp->funcUnit = FuncUnit::S2;
        }
    }
    return birp;
}

void BIRP::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {
    if (executePhase == ExecutePhase::E6) {
        // directs the CPU to the proper location to continue program execution after NMI processing
        auto IRP = *targetMachine->getRegisters()->getReg32ByName(
                CRegName[static_cast<u32>(CRegKind::IRP)])->getDataPtr();
        targetMachine->getRegisters()->getReg32ByName("pc")->updateData(IRP);
        // copy the ITSR register to TSR register
        auto ITSR = *targetMachine->getRegisters()->getReg32ByName(
                CRegName[static_cast<u32>(CRegKind::ITSR)])->getDataPtr();
        targetMachine->getRegisters()->getReg32ByName(CRegName[static_cast<u32>(CRegKind::TSR)])->updateData(ITSR);
    }
}

std::string BIRP::toString() const {
    return getStandardConditionString() + " B " + FuncUnitName[static_cast<u32>(funcUnit)] + " IRP";
}

std::shared_ptr<DspInstruction> BIRP::clone() {
    return std::make_shared<BIRP>(*this);
}
